package userext

import (
	"context"
	"trusteva/app/rbac/model"
	"trusteva/common/jwtx"

	"trusteva/app/rbac/internal/svc"
	"trusteva/app/rbac/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type UserInfoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserInfoLogic {
	return &UserInfoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *UserInfoLogic) UserInfo(req *types.UserInfoRo) (resp *types.UserInfoRsp, err error) {
	claims, err := jwtx.GetClaimsFromCtx(l.ctx)
	if err != nil {
		return nil, err
	}

	resp = new(types.UserInfoRsp)
	var u model.User
	sess := l.svcCtx.DB.WithContext(l.ctx)

	if err := sess.Where("Id=?", claims.Uid).First(&u).Error; err != nil {
		return nil, err
	}
	resp.Uid = u.ID
	resp.Username = u.Username
	resp.Login = u.Login
	resp.Memo = u.Memo
	resp.Roles = u.Roles.Unmarshal()
	resp.Company = u.Company
	resp.Email = u.Email

	var hasRootRole bool

	// 角色
	var roles []model.RoleConfig
	if err := sess.Where("Id in ?", u.Roles.Unmarshal()).
		Find(&roles).Error; err != nil {
		return nil, err
	}
	for _, v := range roles {
		if v.IsRoot == 1 {
			hasRootRole = true
			break
		}
	}

	if hasRootRole {
		var menus []model.MenuConfig
		if err = l.svcCtx.DB.WithContext(l.ctx).Order("Sequence ASC,ID ASC").Find(&menus).Error; err != nil {
			return nil, err
		}

		for _, menu := range menus {
			userMenu := types.UserMenu{
				MenuId:   menu.ID,
				Name:     menu.Name,
				Typ:      menu.Typ,
				ParentId: menu.ParentId,
				Sequence: menu.Sequence,
				Path:     menu.Path,
				Actions:  nil,
			}
			for _, actionId := range menu.Actions.Unmarshal() {
				var action model.ActionConfig
				tx := l.svcCtx.DB.WithContext(l.ctx).Where("Id=?", actionId).Find(&action)
				if err = tx.Error; err != nil {
					return nil, err
				}
				if tx.RowsAffected == 0 {
					continue
				}

				userMenu.Actions = append(userMenu.Actions, types.UserAction{
					ActionId: action.ID,
					Name:     action.Name,
					Path:     action.Path,
					Method:   action.Method,
				})
			}
			resp.Menus = append(resp.Menus, userMenu)
		}
	} else {
		var menuMap = make(map[int]model.MenuConfig)
		var xxMap = make(map[int][]model.ActionConfig)

		for _, v := range u.Roles.Unmarshal() {
			var rmas []model.RoleMenuAction
			if err := sess.Where("RoleId=?", v).Order("MenuId,ActionId ASC").
				Find(&rmas).Error; err != nil {
				return nil, err
			}

			for _, rma := range rmas {
				menu, ok := menuMap[rma.MenuId]
				if !ok {
					if err := sess.Where("Id=?", rma.MenuId).
						Find(&menu).Error; err != nil {
						return nil, err
					}
					menuMap[rma.MenuId] = menu
				}

				var action model.ActionConfig
				if err := sess.Where("Id=?", rma.ActionId).
					Find(&action).Error; err != nil {
					return nil, err
				}
				xxMap[rma.MenuId] = append(xxMap[rma.MenuId], action)
			}
		}

		for menuId, actions := range xxMap {
			menu := menuMap[menuId]
			userMenu := types.UserMenu{
				MenuId:   menuId,
				Name:     menu.Name,
				Typ:      menu.Typ,
				ParentId: menu.ParentId,
				Sequence: menu.Sequence,
				Path:     menu.Path,
				Actions:  nil,
			}

			for _, v := range actions {
				userMenu.Actions = append(userMenu.Actions, types.UserAction{
					ActionId: v.ID,
					Name:     v.Name,
					Path:     v.Path,
					Method:   v.Method,
				})
			}

			resp.Menus = append(resp.Menus, userMenu)
		}
	}

	return
}
